﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Foothill.Common.Logging;
using StructureMap;
using System.Linq;

namespace Foothill.IoC
{
    public static class IocContainer
    {
        public static int RegisterAllTypes(string dir, IList<string> assemblyCandidates)
        {
            IEnumerable<string> assemblies = FileSystemHelper.GetAssemblyNamesInDirectory(dir);

            IList<string> assembliesToRegister = new List<string>();

            foreach (string assemblyName in assemblies)
            {
                if (assemblyCandidates.Contains(assemblyName))
                {            
                    try
                    {
                        RegisterTypesForAssembly(Path.Combine(dir, assemblyName));
                    }
                    catch (Exception)
                    {
                        Log.Error(FoothillModule.Service, string.Format("Failed to register types in the assembly file '{0}//{1}'", dir, assemblyName));
                        throw;
                    }
                }
            }

            return assembliesToRegister.Count;
        }

        public static T GetInstance<T>()
        {
            return ObjectFactory.GetInstance<T>();
        }

        public static object GetInstance(Type t)
        {
            return t.IsAbstract || t.IsInterface ? ObjectFactory.TryGetInstance(t) : ObjectFactory.GetInstance(t);
        }

        public static IEnumerable<object> GetAllInstances(Type t)
        {
            return ObjectFactory.GetAllInstances(t).Cast<object>();
        }

        private static IList<Assembly> GetAssemblies(IEnumerable<string> assemblyNames)
        {
            IList<Assembly> assemblies = new List<Assembly>();

            foreach (string assemblyName in assemblyNames)
            {
                assemblies.Add(Assembly.LoadFrom(assemblyName));
            }

            return assemblies;
        }

        private static void RegisterTypesForAssembly(string assemblyPath)
        {
            Assembly assembly = Assembly.LoadFrom(assemblyPath);

            IList<Type> types = new List<Type>(assembly.GetTypes());

            foreach (Type type in types)
            {
                if (typeof(IocModule).IsAssignableFrom(type) && !type.IsAbstract)
                {
                    IocModule iocModule = (IocModule)Activator.CreateInstance(type);
                    iocModule.RegisterTypes();
                }
            }
        }
    }
}
